#pragma once

namespace RenderSystem
{
	enum ESamplerFilter
	{
		SF_Point,
		SF_Bilinear,
		SF_Trilinear,
		SF_AnisotropicPoint,
		SF_AnisotropicLinear,
	};

	enum ESamplerAddressMode
	{
		AM_Wrap,
		AM_Clamp,
		AM_Mirror
	};

	enum ESamplerMipMapLODBias
	{
		MIPBIAS_None,
		MIPBIAS_Get4
	};

	enum ERasterizerFillMode
	{
		FM_Point,
		FM_Wireframe,
		FM_Solid
	};

	enum ERasterizerCullMode
	{
		CM_None,
		CM_CW,
		CM_CCW
	};

	enum EColorWriteMask
	{
		CW_RED		= 0x01,
		CW_GREEN	= 0x02,
		CW_BLUE		= 0x04,
		CW_ALPHA	= 0x08,

		CW_RGB		= 0x07,
		CW_RGBA		= 0x0f,
	};

	enum ECompareFunction
	{
		CF_Less,
		CF_LessEqual,
		CF_Greater,
		CF_GreaterEqual,
		CF_Equal,
		CF_NotEqual,
		CF_Never,
		CF_Always
	};

	enum EStencilOp
	{
		SO_Keep,
		SO_Zero,
		SO_Replace,
		SO_SaturatedIncrement,
		SO_SaturatedDecrement,
		SO_Invert,
		SO_Increment,
		SO_Decrement
	};

	enum EBlendOperation
	{
		BO_Add,
		BO_Subtract,
		BO_Min,
		BO_Max
	};

	enum EBlendFactor
	{
		BF_Zero,
		BF_One,
		BF_SourceColor,
		BF_InverseSourceColor,
		BF_SourceAlpha,
		BF_InverseSourceAlpha,
		BF_DestAlpha,
		BF_InverseDestAlpha,
		BF_DestColor,
		BF_InverseDestColor
	};

	enum EVertexElementType
	{
		VET_None,
		VET_Float1,
		VET_Float2,
		VET_Float3,
		VET_Float4,
		VET_PackedNormal,	// FPackedNormal
		VET_UByte4,
		VET_UByte4N,
		VET_Color,
		VET_Short2,
		VET_Short2N,		// 16 bit word normalized to (value/32767.0,value/32767.0,0,0,1)
		VET_Half2,			// 16 bit float using 1 bit sign, 5 bit exponent, 10 bit mantissa 
		VET_MAX
	};

	enum EVertexElementUsage
	{
		VEU_Position,
		VEU_TextureCoordinate,
		VEU_BlendWeight,
		VEU_BlendIndices,
		VEU_Normal,
		VEU_Tangent,
		VEU_Binormal,
		VEU_Color
	};

	enum ECubeFace
	{
		CubeFace_PosX=0,
		CubeFace_NegX,
		CubeFace_PosY,
		CubeFace_NegY,
		CubeFace_PosZ,
		CubeFace_NegZ,
		CubeFace_MAX
	};

	enum TextureAddress
	{
		TA_Wrap                 =0,
		TA_Clamp                =1,
		TA_Mirror               =2,
		TA_MAX                  =3,
	};
	enum TextureFilter
	{
		TF_Nearest              =0,
		TF_Linear               =1,
		TF_MAX                  =2,
	};
	enum EPixelFormat
	{
		PF_Unknown              =0,
		PF_A32B32G32R32F        =1,
		PF_A8R8G8B8             =2,
		PF_G8                   =3,
		PF_G16                  =4,
		PF_DXT1                 =5,
		PF_DXT3                 =6,
		PF_DXT5                 =7,
		PF_UYVY                 =8,
		PF_FloatRGB             =9,
		PF_FloatRGBA            =10,
		PF_DepthStencil         =11,
		PF_ShadowDepth          =12,
		PF_FilteredShadowDepth  =13,
		PF_R32F                 =14,
		PF_G16R16               =15,
		PF_G16R16F              =16,
		PF_G16R16F_FILTER       =17,
		PF_G32R32F              =18,
		PF_A2B10G10R10          =19,
		PF_A16B16G16R16         =20,
		PF_D24                  =21,
		PF_R16F                 =22,
		PF_R16F_FILTER          =23,
		PF_BC5                  =24,
		PF_V8U8                 =25,
		PF_MAX                  =26,
	};
	enum TextureCompressionSettings
	{
		TC_Default              =0,
		TC_Normalmap            =1,
		TC_Displacementmap      =2,
		TC_NormalmapAlpha       =3,
		TC_Grayscale            =4,
		TC_HighDynamicRange     =5,
		TC_OneBitAlpha          =6,
		TC_NormalmapUncompressed=7,
		TC_NormalmapBC5         =8,
		TC_MAX                  =9,
	};

	/**
	*	Resource usage flags - for vertex and index buffers.
	*/
	enum EResourceUsageFlags
	{
		// Mutually exclusive flags
		RUF_Static		= 0x01,		// The resource will be created, filled, and never repacked.
		RUF_Dynamic		= 0x02,		// The resource will be repacked in-frequently.
		RUF_Volatile	= 0x04,		// The resource will be repacked EVERY frame.

		// The following flags can be OR:d in
		RUF_WriteOnly	= 0x80,		// The resource data will never be read from.

		// Helper bit-masks
		RUF_AnyDynamic	= (RUF_Dynamic|RUF_Volatile),
	};

	struct VertexElement
	{
		BYTE StreamIndex;
		BYTE Offset;
		BYTE Type;
		BYTE Usage;
		BYTE UsageIndex;
		bool bUseInstanceIndex;

		VertexElement() {}
		VertexElement(BYTE InStreamIndex,BYTE InOffset,BYTE InType,BYTE InUsage,BYTE InUsageIndex,bool bInUseInstanceIndex = false):
		StreamIndex(InStreamIndex),
			Offset(InOffset),
			Type(InType),
			Usage(InUsage),
			UsageIndex(InUsageIndex),
			bUseInstanceIndex(bInUseInstanceIndex)
		{}
		/**
		* Suppress the compiler generated assignment operator so that padding won't be copied.
		* This is necessary to get expected results for code that zeros, assigns and then CRC's the whole struct.
		*/
		void operator = (const VertexElement& Other)
		{
			StreamIndex = Other.StreamIndex;
			Offset = Other.Offset;
			Type = Other.Type;
			Usage = Other.Usage;
			UsageIndex = Other.UsageIndex;
			bUseInstanceIndex = Other.bUseInstanceIndex;
		}
	};


	struct FSamplerStateInitializerRHI
	{
		ESamplerFilter Filter;
		ESamplerAddressMode AddressU;
		ESamplerAddressMode AddressV;
		ESamplerAddressMode AddressW;
		ESamplerMipMapLODBias MipBias;
	};
	struct FRasterizerStateInitializerRHI
	{
		ERasterizerFillMode FillMode;
		ERasterizerCullMode CullMode;
		FLOAT DepthBias;
		FLOAT SlopeScaleDepthBias;
	};
	struct FDepthStateInitializerRHI
	{
		bool bEnableDepthWrite;
		ECompareFunction DepthTest;
	};

	struct FStencilStateInitializerRHI
	{
		FStencilStateInitializerRHI(
			bool bInEnableFrontFaceStencil = FALSE,
			ECompareFunction InFrontFaceStencilTest = CF_Always,
			EStencilOp InFrontFaceStencilFailStencilOp = SO_Keep,
			EStencilOp InFrontFaceDepthFailStencilOp = SO_Keep,
			EStencilOp InFrontFacePassStencilOp = SO_Keep,
			bool bInEnableBackFaceStencil = FALSE,
			ECompareFunction InBackFaceStencilTest = CF_Always,
			EStencilOp InBackFaceStencilFailStencilOp = SO_Keep,
			EStencilOp InBackFaceDepthFailStencilOp = SO_Keep,
			EStencilOp InBackFacePassStencilOp = SO_Keep,
			DWORD InStencilReadMask = 0xFFFFFFFF,
			DWORD InStencilWriteMask = 0xFFFFFFFF,
			DWORD InStencilRef = 0) :
		bEnableFrontFaceStencil(bInEnableFrontFaceStencil),
			FrontFaceStencilTest(InFrontFaceStencilTest),
			FrontFaceStencilFailStencilOp(InFrontFaceStencilFailStencilOp),
			FrontFaceDepthFailStencilOp(InFrontFaceDepthFailStencilOp),
			FrontFacePassStencilOp(InFrontFacePassStencilOp),
			bEnableBackFaceStencil(bInEnableBackFaceStencil),
			BackFaceStencilTest(InBackFaceStencilTest),
			BackFaceStencilFailStencilOp(InBackFaceStencilFailStencilOp),
			BackFaceDepthFailStencilOp(InBackFaceDepthFailStencilOp),
			BackFacePassStencilOp(InBackFacePassStencilOp),
			StencilReadMask(InStencilReadMask),
			StencilWriteMask(InStencilWriteMask),
			StencilRef(InStencilRef)
		{
		}

		bool bEnableFrontFaceStencil;
		ECompareFunction FrontFaceStencilTest;
		EStencilOp FrontFaceStencilFailStencilOp;
		EStencilOp FrontFaceDepthFailStencilOp;
		EStencilOp FrontFacePassStencilOp;
		bool bEnableBackFaceStencil;
		ECompareFunction BackFaceStencilTest;
		EStencilOp BackFaceStencilFailStencilOp;
		EStencilOp BackFaceDepthFailStencilOp;
		EStencilOp BackFacePassStencilOp;
		DWORD StencilReadMask;
		DWORD StencilWriteMask;
		DWORD StencilRef;
	};
	struct FBlendStateInitializerRHI
	{
		EBlendOperation ColorBlendOperation;
		EBlendFactor ColorSourceBlendFactor;
		EBlendFactor ColorDestBlendFactor;
		EBlendOperation AlphaBlendOperation;
		EBlendFactor AlphaSourceBlendFactor;
		EBlendFactor AlphaDestBlendFactor;
		ECompareFunction AlphaTest;
		BYTE AlphaRef;
	};

	enum EPrimitiveType
	{
		PT_TriangleList = 0,
		PT_TriangleStrip = 1,
		PT_LineList = 2,
		PT_QuadList = 3,
		PT_TessellatedQuadPatch = 4,	// Xbox-specific

		PT_NumBits = 3
	};

	enum EParticleEmitterType
	{
		PET_None = 0,		// Not a particle emitter
		PET_Sprite = 1,		// Sprite particle emitter
		PET_SubUV = 2,		// SubUV particle emitter
		PET_Mesh = 3,		// Mesh emitter

		PET_NumBits = 2
	};

	// Pixel shader constants that are reserved by the Engine.
	enum EPixelShaderRegisters
	{
		PSR_ColorBiasFactor = 0,			// Factor applied to the color output from the pixelshader
		PSR_ScreenPositionScaleBias = 1,	// Converts projection-space XY coordinates to texture-space UV coordinates
		PSR_MinZ_MaxZ_Ratio = 2,			// Converts device Z values to clip-space W values
	};

	// Vertex shader constants that are reserved by the Engine.
	enum EVertexShaderRegister
	{
		VSR_ViewProjMatrix = 0,		// View-projection matrix, transforming from World space to Projection space
		VSR_ViewOrigin = 4,			// World space position of the view's origin (camera position)
	};

	/**
	*	Tessellation mode, to be used with RHISetTessellationMode.
	*/
	enum ETessellationMode
	{
		TESS_Discrete = 0,
		TESS_Continuous = 1,
		TESS_PerEdge = 2,
	};

	/**
	*	Screen Resolution
	*/
	struct FScreenResolutionRHI
	{
		DWORD	Width;
		DWORD	Height;
		DWORD	RefreshRate;
	};

	typedef std::vector< FScreenResolutionRHI > FScreenResolutionArray;

	//typedef TArray<FScreenResolutionRHI>	FScreenResolutionArray;

	/** A macro that calls the provided macro with the name and parent's name of each RHI resource type. */
#define ENUM_RHI_RESOURCE_TYPES(EnumerationMacro) \
	EnumerationMacro(SamplerState,None) \
	EnumerationMacro(RasterizerState,None) \
	EnumerationMacro(DepthState,None) \
	EnumerationMacro(StencilState,None) \
	EnumerationMacro(BlendState,None) \
	EnumerationMacro(VertexDeclaration,None) \
	EnumerationMacro(VertexShader,None) \
	EnumerationMacro(PixelShader,None) \
	EnumerationMacro(BoundShaderState,None) \
	EnumerationMacro(IndexBuffer,None) \
	EnumerationMacro(VertexBuffer,None) \
	EnumerationMacro(Surface,None) \
	EnumerationMacro(Texture,None) \
	EnumerationMacro(Texture2D,Texture) \
	EnumerationMacro(TextureCube,Texture) \
	EnumerationMacro(SharedTexture2D,Texture2D) \
	EnumerationMacro(SharedMemoryResource,None) \
	EnumerationMacro(OcclusionQuery,None) \
	EnumerationMacro(Viewport,None)

	/** An enumeration of the different RHI reference types. */
	enum ERHIResourceTypes
	{
		RRT_None,

#define DECLARE_RESOURCETYPE_ENUM(Type,ParentType) RRT_##Type,
		ENUM_RHI_RESOURCE_TYPES(DECLARE_RESOURCETYPE_ENUM)
#undef DECLARE_RESOURCETYPE_ENUM
	};

	/** Flags used for texture creation */
	enum ETextureCreateFlags
	{
		// Texture is encoded in sRGB gamma space
		TexCreate_SRGB					= 1<<0,
		// Texture can be used as a resolve target (normally not stored in the texture pool)
		TexCreate_ResolveTargetable		= 1<<1,
		// Texture is a depth stencil format that can be sampled
		TexCreate_DepthStencil			= 1<<2,
		// Texture will be created without a packed miptail
		TexCreate_NoMipTail				= 1<<3,
		// Texture will be created with an un-tiled format
		TexCreate_NoTiling				= 1<<4,
		// Texture that for a resolve target will only be written to/resolved once
		TexCreate_WriteOnce				= 1<<5,
		// Texture that may be updated every frame
		TexCreate_Dynamic				= 1<<6,
		// Texture that didn't go through the offline cooker (normally not stored in the texture pool)
		TexCreate_Uncooked				= 1<<7,
		// Allow silent texture creation failure
		TexCreate_AllowFailure			= 1<<8,
		// Disable automatic defragmentation if the initial texture memory allocation fails.
		TexCreate_DisableAutoDefrag		= 1<<9,
		// Create the texture with automatic -1..1 biasing
		TexCreate_BiasNormalMap			= 1<<10,
	};

	/** Flags used for targetable surface creation */
	enum ETargetableSurfaceCreateFlags
	{
		// Without this the surface may simply be an alias for the texture's memory. Note that you must still resolve the surface.
		TargetSurfCreate_Dedicated		= 1<<0,
		// Surface must support being read from by RHIReadSurfaceData.
		TargetSurfCreate_Readable		= 1<<1,
		// Surface will be only written to one time, in case that helps the platform
		TargetSurfCreate_WriteOnce		= 1<<2,
		// Surface will be created as multisampled.  This implies TargetSurfCreate_Dedicated, unless multisampling is disabled.
		TargetSurfCreate_Multisample	= 1<<3,
	};

	/**
	* Settings that determines whether SceneDepth are looked up normally, or specially for projected shadow passes.
	* PS3 reads SceneDepth straight from the depth buffer during shadow passes.
	*/
	enum ESceneDepthUsage
	{
		SceneDepthUsage_Normal = 0,
		SceneDepthUsage_ProjectedShadows,
	};

	// Define the statically bound RHI methods with the RHI name prefix.
//#define DEFINE_RHIMETHOD(Type,Name,ParameterTypesAndNames,ParameterNames,ReturnStatement,NullImplementation) extern Type RHI##Name ParameterTypesAndNames
//#include "RHIMethods.h"
//#undef DEFINE_RHIMETHOD


	//struct FResolveParams
	//{
	//	/** used to specify face when resolving to a cube map texture */
	//	ECubeFace CubeFace;
	//	/** resolve RECT bounded by [X1,Y1]..[X2,Y2]. Or -1 for fullscreen */
	//	INT X1,Y1,X2,Y2;
	//	/** Texture to resolve to. If NULL, it will resolve to the texture associated with the rendertarget. */
	//	FTexture2DRHIParamRef ResolveTarget;
	//	/** constructor */
	//	FResolveParams(INT InX1=-1, INT InY1=-1, INT InX2=-1, INT InY2=-1, ECubeFace InCubeFace=CubeFace_PosX, FTexture2DRHIParamRef InResolveTarget=NULL)
	//		:	CubeFace(InCubeFace)
	//		,	X1(InX1), Y1(InY1), X2(InX2), Y2(InY2)
	//		,	ResolveTarget(InResolveTarget)
	//	{}
	//};

	/** The maximum number of vertex elements which can be used by a vertex declaration. */
	enum { MaxVertexElementCount = 16 };

	typedef std::vector<VertexElement> VertexDeclarationElementList;

	//custom type define
	//typedef std::vector<BYTE>	ByteArray;
	typedef DWORD*				ByteArray;

	typedef void FResourceArrayInterface;
	typedef void FResourceBulkDataInterface;

	struct FPixelFormatInfo
	{
		const TCHAR*	Name;
		INT				BlockSizeX,
			BlockSizeY,
			BlockSizeZ,
			BlockBytes,
			NumComponents;
		/** Platform specific token, e.g. D3DFORMAT with D3DDrv										*/
		DWORD			PlatformFormat;
		/** Format specific internal flags, e.g. whether SRGB is supported with this format		*/
		DWORD			Flags;
		/** Whether the texture format is supported on the current platform/ rendering combination	*/
		bool			Supported;
	};

	extern FPixelFormatInfo GPixelFormats[];		// Maps members of EPixelFormat to a FPixelFormatInfo describing the format.
}